#include<iostream>
#include<unistd.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<cstdlib>
#include<cstring>

using namespace std;

//必须得等待，否则可能子进程会变成僵尸进程
void handler(int signo)
{
    cout<<"catch a signal, num: "<<getpid()<<endl;
    pid_t rid;
    while((rid==waitpid(-1,nullptr,WNOHANG))>0)
    {
        cout << "I am proccess: " << getpid() << " catch a signo: " << signo << "child process quit: " << rid << endl;
    }
}
int main()
{
    signal(17,handler);
    pid_t id=fork();
    // if(id==0)//child
    // {
    //     while(true)
    //     {
    //         cout<<"I am child process,pid: "<<getpid()<<"ppid: "<<getppid()<<endl;
    //         sleep(5);
    //         break;
    //     }
    //     cout<<"child quit"<<endl;
    //     //若不加，子进程会冒充父进程
    //     exit(0);
    // }
    for (int i = 0; i < 10; i++)
    {
        pid_t id = fork();
        if (id == 0)
        {
            while (true)
            {
                cout << "I am child process: " << getpid() << ", ppid: " << getppid() << endl;
                sleep(5);
                break;
            }
            cout << "child quit!!!" << endl;
            exit(0);
        }
        // sleep(rand()%5+3);
        sleep(1);
    }
    //father
    while(true)
    {
        cout << "I am father process: " << getpid() << endl;
        sleep(1);
    }

    return 0;
}



















// //解决信号修改变量时的编译器优化冲突，，每次都要从内存重新读，别优化到寄存器！
// volatile int flag=0;
// // int flag=0;
// void handler(int signo)
// {
//     cout<<"I catch a signal"<<signo<<endl;
//     flag=1;
// }

// int main()
// {
//     signal(2,handler);
//     while(!flag);
//     cout<<"process quit"<<endl;
//     return 0;
// }

// void PrintPending()
// {
//     sigset_t set;
//     sigpending(&set);

//     for(int signo=1;signo<=31;signo++)
//     {
//         if(sigismember(&set,signo))
//         {
//             cout<<"1";
//         }
//         else
//         {
//             cout<<"0";
//         }
//     }
//     cout<<"\n\n";
// }


// void handler(int signo)
// {
//     cout<<"I get a signal,num is :"<<signo<<endl;
//     while(true)
//     {
//         PrintPending();
//         sleep(1);
//     }
// }

// // 1.pending位图，什么时候1 -> 0 ? 执行信号捕捉前，先清零，再调用
// // 2.信号被处理的时候，对应的信号也会被放到block表，防止信号捕捉被嵌套调用

// int main()
// {
//     struct sigaction act,oact;
//     //内存字节级清零
//     memset(&act,0,sizeof(act));
//     memset(&oact,0,sizeof(oact));
//     //信号集合逻辑清空
//     sigemptyset(&act.sa_mask);
//     sigemptyset(&oact.sa_mask);
//     sigaddset(&act.sa_mask,1);
//     sigaddset(&act.sa_mask,3);
//     sigaddset(&act.sa_mask,4);
//     act.sa_handler=handler;
//     sigaction(2,&act,&oact);

//     while(true)
//     {
//         cout<<"I am a process: "<<getpid()<<endl;
//         sleep(1);
//     }

//     return 0;
// }


// void handler(int signo)
// {
//     cout<<"I get a signal,num is :"<<signo<<endl;
// }
// void PrintPending(sigset_t &pending)
// {
//     for(int signo=1;signo<=31;signo++)
//     {
//         if(sigismember(&pending,signo))
//         {
//             cout<<"1";
//         }
//         else
//         {
//             cout<<"0";
//         }
//     }
//     cout<<"\n\n";
// }

// int main()
// {
//     //将所以信号进行屏蔽？
//     sigset_t bset,oset;
//     sigemptyset(&bset);
//     sigemptyset(&oset);
//     for(int i=1;i<=31;i++)
//     {
//         sigaddset(&bset,i);
//     }
//     sigprocmask(SIG_SETMASK,&bset,&oset);
//     sigset_t pending;
//     while(true)
//     {
//         int n=sigpending(&pending);
//         if(n<0)
//             continue;
//         PrintPending(pending);
//         sleep(1);

//     }

//     // //对2号进行捕捉
//     // // signal(2,handler);
//     // //先对2号进行屏蔽
//     // sigset_t bset,oset; //在哪里开辟空间的？在用户栈上，属于用户区
//     // sigemptyset(&bset);
//     // sigemptyset(&oset);
//     // sigaddset(&bset,2); //此时并没有把2号屏蔽了，并没有设置进你的task_struct里
//     // //1调用系统调用接口，将数据设置进内核
//     // sigprocmask(SIG_SETMASK,&bset,&oset);
//     // // 2.重复打印当前进程的pending表
//     // sigset_t pending;
//     // int cnt=0;
//     // while(true)
//     // {
//     //     //获取pending,********参数不是bset******
//     //     int n=sigpending(&pending);
//     //     if(n<0)
//     //         continue;
//     //     //打印pending
//     //     PrintPending(pending);
//     //     sleep(1);
//     //     cnt++;
//     //     //解除阻塞
//     //     if(cnt==20)
//     //     {
//     //         cout<<"unblock 2 signal"<<endl;
//     //         sigprocmask(SIG_SETMASK,&oset,nullptr);
//     //     }
//     // }

//     return 0;
// }


// int main()
// {
//     // int a=10;
//     // int b=0;
//     // int c=a/b;
//     pid_t id=fork();
//     if(id<0)
//     {
//         perror("fork");
//         exit(1);
//     }
//     else if(id==0)//child
//     {
//         int cnt=10;
//         while(cnt)
//         {
//             cout<<"I am a child process, pid: "<<getpid()<<endl;
//             sleep(1);
//             cnt--;
//         }

//     }
//     //father
//     int status=0;
//     pid_t rid=waitpid(id,&status,0);
//     if(rid==id)
//     {
//         cout<<"child quit info , rid: "<<rid<<"exit code: "<<((status>>8)&0xFF)<<"signal code: "<<(status&0x7F)
//         <<"dump code "<<((status>>7)&1)<<endl;
//     }
//     return 0;
// }

// void myhandler(int signo)
// {
//     cout<<"I get a signal,num: "<<signo<<"pid: "<<getpid()<<endl;
// }
// int main()
// {
//     //signal(SIGSEGV,myhandler);
//     cout<<"point error before"<<endl;
//     sleep(2);
//     char buffer[1024];
//     int n=1024;
//     n=read(4,buffer,n);
//     printf("%d\n",n);
//     perror("read");
//     int *p=nullptr;
//     *p=100; //野指针
//     cout<<"point error after"<<endl;
//     sleep(1);
//     return 0;
// }

// void myhandler(int signo)
// {
//     cout<<"I get a signal,num: "<<signo<<"pid: "<<getpid()<<endl;
//     sleep(1);
// }
// int main()
// {
//     int cnt=5;
//     signal(SIGFPE,myhandler);
//     // int n=alarm(2);
//     // int *p=NULL;
//     // *p=100;
//     int a=10;
//     int b=0;
//     int c=a/b;
//     while(true)
//     {
//         cout<<"I am runing,pid: "<<getpid()<<"cnt: "<<cnt<<endl;
//         sleep(1);
//     }
//     return 0;
// }

